package com.doubao.hardware.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.doubao.hardware.context.UserContext;
import com.doubao.hardware.dto.ApiResponse;
import com.doubao.hardware.entity.HardwareDeviceEntity;
import com.doubao.hardware.mapper.HardwareDeviceMapper;
import com.doubao.hardware.service.DeviceRegistrationService;
import com.doubao.hardware.service.MqttService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 设备控制器
 * 提供设备查询和管理的REST API接口
 */
@RestController
@RequestMapping("/hardware")
@RequiredArgsConstructor
@Slf4j
public class DeviceController {

    private final HardwareDeviceMapper hardwareDeviceMapper;
    private final DeviceRegistrationService deviceRegistrationService;
    private final MqttService mqttService;
    private final ObjectMapper objectMapper;  // 添加这一行

    @Value("${mqtt.baidu.topic}")
    private String mqttTopic;

    // 使用内存缓存记录设备的最后一次配置，避免重复发送相同的配置
    private final Map<String, String> deviceConfigCache = new ConcurrentHashMap<>();

    /**
     * 获取用户的设备列表
     * @param userId 用户ID
     * @return 设备列表
     */
    @GetMapping("/user")
    public ApiResponse<List<HardwareDeviceEntity>> getUserDevices(
            @RequestParam Long userId) {
        try {
            List<HardwareDeviceEntity> devices = hardwareDeviceMapper.selectByUserId(userId);
            return ApiResponse.success(devices);
        } catch (Exception e) {
            log.error("获取用户设备列表失败", e);
            return ApiResponse.error("获取设备列表失败: " + e.getMessage());
        }
    }

    /**
     * 分页获取设备列表
     * @param page 页码
     * @param size 每页大小
     * @param userId 用户ID (可选)
     * @param isOnline 在线状态 (可选)
     * @param status 设备状态 (可选)
     * @return 分页设备列表
     */
    @GetMapping("/list")
    public ApiResponse<Map<String, Object>> listDevices(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size,
            @RequestParam(required = false) Long userId,
            @RequestParam(required = false) Integer isOnline,
            @RequestParam(required = false) Integer status) {

        try {
            LambdaQueryWrapper<HardwareDeviceEntity> queryWrapper = new LambdaQueryWrapper<>();

            // 添加查询条件
            if (userId != null) {
                queryWrapper.eq(HardwareDeviceEntity::getUserId, userId);
            }

            if (isOnline != null) {
                queryWrapper.eq(HardwareDeviceEntity::getIsOnline, isOnline);
            }

            if (status != null) {
                queryWrapper.eq(HardwareDeviceEntity::getStatus, status);
            }

            // 按最后在线时间倒序排序
            queryWrapper.orderByDesc(HardwareDeviceEntity::getLastOnlineTime);

            // 执行分页查询
            Page<HardwareDeviceEntity> pageResult = hardwareDeviceMapper.selectPage(
                    new Page<>(page, size), queryWrapper);

            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("total", pageResult.getTotal());
            result.put("pages", pageResult.getPages());
            result.put("current", pageResult.getCurrent());
            result.put("size", pageResult.getSize());
            result.put("records", pageResult.getRecords());

            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("分页获取设备列表失败", e);
            return ApiResponse.error("获取设备列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取设备详情
     * @param deviceId 设备ID
     * @return 设备详情
     */
    @GetMapping("/{deviceId}")
    public ApiResponse<HardwareDeviceEntity> getDeviceDetail(@PathVariable Long deviceId) {
        try {
            HardwareDeviceEntity device = hardwareDeviceMapper.selectById(deviceId);
            if (device == null) {
                return ApiResponse.error(404, "设备不存在");
            }
            return ApiResponse.success(device);
        } catch (Exception e) {
            log.error("获取设备详情失败", e);
            return ApiResponse.error("获取设备详情失败: " + e.getMessage());
        }
    }

    /**
     * 更新设备在线状态
     * @param deviceId 设备ID
     * @param isOnline 是否在线
     * @return 更新结果
     */
    @PutMapping("/{deviceId}/online")
    public ApiResponse<Void> updateDeviceOnlineStatus(
            @PathVariable Long deviceId,
            @RequestParam Boolean isOnline) {
        try {
            deviceRegistrationService.updateDeviceOnlineStatus(deviceId, isOnline);
            return ApiResponse.success("设备在线状态更新成功", null);
        } catch (Exception e) {
            log.error("更新设备在线状态失败", e);
            return ApiResponse.error("更新设备在线状态失败: " + e.getMessage());
        }
    }

    /**
     * 更新设备昵称
     * @param deviceId 设备ID
     * @param nickname 设备昵称
     * @return 更新结果
     */
    @PutMapping("/{deviceId}/nickname")
    public ApiResponse<Void> updateDeviceNickname(
            @PathVariable Long deviceId,
            @RequestParam String nickname) {
        try {
            HardwareDeviceEntity device = hardwareDeviceMapper.selectById(deviceId);
            if (device == null) {
                return ApiResponse.error(404, "设备不存在");
            }

            device.setNickname(nickname);
            hardwareDeviceMapper.updateById(device);

            return ApiResponse.success("设备昵称更新成功", null);
        } catch (Exception e) {
            log.error("更新设备昵称失败", e);
            return ApiResponse.error("更新设备昵称失败: " + e.getMessage());
        }
    }

    @PostMapping("/device")
    public ApiResponse<HardwareDeviceEntity> createDevice(@RequestBody HardwareDeviceEntity deviceData) {
        try {
            // 设置必要的默认值和校验
            if (deviceData.getNickname() == null || deviceData.getNickname().isEmpty()) {
                return ApiResponse.error("设备名称不能为空");
            }

            // 设置创建时间
            deviceData.setCreatedAt(LocalDateTime.now());
            deviceData.setUpdatedAt(LocalDateTime.now());

            // 插入设备
            hardwareDeviceMapper.insert(deviceData);

            return ApiResponse.success("设备创建成功", deviceData);
        } catch (Exception e) {
            log.error("创建设备失败", e);
            return ApiResponse.error("创建设备失败: " + e.getMessage());
        }
    }

    // 原有方法保持不变
    @PutMapping("/device/{deviceId}")
    public ApiResponse<HardwareDeviceEntity> updateDevice(
            @PathVariable Long deviceId,
            @RequestBody HardwareDeviceEntity deviceData) {
        try {
            // 先检查设备是否存在
            HardwareDeviceEntity existingDevice = hardwareDeviceMapper.selectById(deviceId);
            if (existingDevice == null) {
                return ApiResponse.error(404, "设备不存在");
            }

            // 确保日志记录完整的请求数据
            log.info("收到更新设备请求 - DeviceID: {}, 请求数据: {}",
                    deviceId,
                    objectMapper.writeValueAsString(deviceData)
            );

            // 设置ID，确保更新正确的设备
            deviceData.setId(deviceId);
            deviceData.setUpdatedAt(LocalDateTime.now());

            // 保留原始的一些字段值
            deviceData.setCreatedAt(existingDevice.getCreatedAt());

            // 处理 isOnline 字段
            if (deviceData.getIsOnline() == null) {
                deviceData.setIsOnline(existingDevice.getIsOnline());
            }

            // 更新设备
            hardwareDeviceMapper.updateById(deviceData);

            return ApiResponse.success("设备更新成功", deviceData);
        } catch (Exception e) {
            log.error("更新设备失败", e);
            return ApiResponse.error("更新设备失败: " + e.getMessage());
        }
    }

    /**
     * 删除硬件设备
     * @param deviceId 设备ID
     * @return 删除结果
     */
    @DeleteMapping("/device/{deviceId}")
    public ApiResponse<Void> deleteDevice(@PathVariable Long deviceId) {
        try {
            // 检查是否登录
            if (!UserContext.isUserLoggedIn()) {
                return ApiResponse.error(401, "未登录");
            }

            // 获取当前登录用户ID
            Long currentUserId = UserContext.getUserId();

            // 先检查设备是否存在
            HardwareDeviceEntity existingDevice = hardwareDeviceMapper.selectById(deviceId);
            if (existingDevice == null) {
                return ApiResponse.error(404, "设备不存在");
            }

            // 检查当前用户是否有权限删除设备
            if (!existingDevice.getUserId().equals(currentUserId)) {
                return ApiResponse.error(403, "无权删除此设备");
            }

            // 删除设备
            hardwareDeviceMapper.deleteById(deviceId);

            return ApiResponse.success("设备删除成功");
        } catch (Exception e) {
            log.error("删除设备失败", e);
            return ApiResponse.error("删除设备失败: " + e.getMessage());
        }
    }

    /**
     * 通过MAC地址获取设备
     * @param macAddress MAC地址
     * @return 设备详情
     */
    @GetMapping("/by-mac/{macAddress}")
    public ApiResponse<HardwareDeviceEntity> getDeviceByMac(@PathVariable String macAddress) {
        try {
            HardwareDeviceEntity device = hardwareDeviceMapper.selectByMacAddress(macAddress);
            if (device == null) {
                return ApiResponse.error(404, "设备不存在");
            }
            return ApiResponse.success(device);
        } catch (Exception e) {
            log.error("通过MAC地址获取设备失败", e);
            return ApiResponse.error("获取设备失败: " + e.getMessage());
        }
    }

    /**
     * 发送MQTT消息
     * @param requestBody 请求体，包含payload字段
     * @return 发送结果
     */
    @PostMapping("/mqtt/send")
    public ApiResponse<Void> sendMqttMessage(@RequestBody Map<String, String> requestBody) {
        try {
            String payload = requestBody.get("payload");
            if (payload == null || payload.isEmpty()) {
                return ApiResponse.error("消息内容不能为空");
            }

            log.info("准备发送MQTT消息到主题: {}", mqttTopic);
            log.debug("消息内容: {}", payload);

            // 提取MAC地址和设备配置，检查是否重复发送
            String configHash = String.valueOf(payload.hashCode());

            // 使用MqttService发送消息
            boolean success = mqttService.sendMessage(payload);

            if (success) {
                return ApiResponse.success("消息发送成功", null);
            } else {
                return ApiResponse.error("消息发送失败，MQTT连接可能已断开");
            }
        } catch (Exception e) {
            log.error("发送MQTT消息失败", e);
            return ApiResponse.error("发送消息失败: " + e.getMessage());
        }
    }
}